/**
 * Description:
 * Class Name:VarHandleTest
 * Date:2022/2/22 13:24
 *
 * @author LTisme
 * @version JAVA17
 */
package 疯狂Java讲义.第7章_Java基础类库._7_6_变量处理和方法处理._7_6_2_Java9增强的VarHandle;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.Arrays;

class User{
    String name;
    static int MAX_AGE;
}

public class VarHandleTest {
    public static void main(String[] args) throws Throwable{
        var sa = new String[] {"Java", "Kotlin", "Go"};
        // 获取一个String[]数组的VarHandle 对象
        var avh = MethodHandles.arrayElementVarHandle(String[].class);
        // 比较并设置：如果第三个元素为Go，则该元素被设为Lua
        var r = avh.compareAndSet(sa, 2, "Go", "Lua");      // 从左到右分别传入String[]数组对象，索引，目标值，重设值
        // 输出结果比较
        System.out.println(r);                              // 输出true
        // 看到第3个元素被替换成了Lua
        System.out.println(Arrays.toString(sa));
        // 获取sa数组的第2个元素
        System.out.println(avh.get(sa, 1));                 // 输出Kotlin
        // 获取并设置：返回第3个元素，并将第3个元素设为Swift
        System.out.println(avh.getAndSet(sa, 2, "Swift"));
        // 再次输出数组，可以看到第3个元素已经被替换成了Swift
        System.out.println(Arrays.toString(sa));

        // 用findVarHandle方法获取User类中名为name、类型为String的实例变量
        VarHandle vh1 = MethodHandles.lookup().findVarHandle(User.class, "name", String.class);
        var user = new User();
        // 通过VarHandle获取实例变量的值，实例变量的话需要传入对象作为调用者
        System.out.println(vh1.get(user));                  // 输出null
        // 通过VarHandle来设置指定实例变量的值
        vh1.set(user, "孙悟空");
        System.out.println(user.name);                      // 输出孙悟空

        // 用findStaticVarHandle方法获取User类中名为MAX_AGE、类型为Integer的类变量
        VarHandle vh2 = MethodHandles.lookup().findStaticVarHandle(User.class, "MAX_AGE", int.class);
        // 通过VarHandle获取指定类变量的值
        vh2.set(100);
        System.out.println(User.MAX_AGE);
    }
}

// 输出结果为：
//true
//[Java, Kotlin, Lua]
//Kotlin
//Lua
//[Java, Kotlin, Swift]
//null
//孙悟空
//100
